package com.simple.relaxed.view;

import com.simple.relaxed.anno.InitComponent;
import com.simple.relaxed.anno.Layout;
import com.simple.relaxed.anno.OnClick;
import com.simple.relaxed.anno.OnLongClick;
import com.simple.relaxed.exception.AnnotationAbsenceException;
import ohos.agp.components.Component;
import ohos.agp.components.LayoutScatter;
import ohos.agp.window.dialog.PopupDialog;
import ohos.app.Context;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 继承此类，快速创建简易的悬浮窗口
 */
public abstract class SimplePopup extends PopupDialog {

    protected Context context;

    public SimplePopup(Context context, Component contentComponent) {
        super(context, contentComponent);
        this.context = context;
        init();
    }

    public SimplePopup(Context context, Component contentComponent, int width, int height) {
        super(context, contentComponent, width, height);
        this.context = context;
        init();
    }

    private void init() {
        // 获取下拉导航栏的视图
        int layout = getLayout();
        Component component = LayoutScatter.getInstance(context).parse(layout, null, false);
        setCustomComponent(component);
        // 初始化视图组件
        initComponent(component);
        // 注册点击事件
        initClick(component);
        // 设置长按事件
        initLongClick(component);
        setAutoClosable(true);
    }

    /**
     * 重写此方法可以定制视图获取方法
     *
     * @return 要被加载的视图id
     */
    protected int getLayout() {
        Layout layout = this.getClass().getDeclaredAnnotation(Layout.class);
        if (layout == null) {
            throw new AnnotationAbsenceException("缺少注解 ".concat(Layout.class.getName()));
        }
        return layout.layoutId();
    }

    /**
     * 重写此方法，定制组件初始化方法
     *
     * @param component 主视图组件，可以使用此组件找到布局中的所有子元素
     */
    protected void initComponent(Component component) {
        Class<? extends SimplePopup> aClass = this.getClass();
        Field[] fields = aClass.getDeclaredFields();
        for (Field field : fields) {
            InitComponent initComponent = field.getDeclaredAnnotation(InitComponent.class);
            if (initComponent == null) {
                continue;
            }
            Component c = component.findComponentById(initComponent.componentId());
            try {
                field.setAccessible(true);
                field.set(this, c);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 重写此方法，定制组件点击事件注入逻辑
     *
     * @param component 此悬浮穿的主布局对象，可以通过此对象找到当前悬浮穿内，需要注入点击事件的Component对象
     */
    protected void initClick(Component component) {
        Class<? extends SimplePopup> aClass = this.getClass();
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            OnClick onClick = method.getDeclaredAnnotation(OnClick.class);
            if (onClick == null) {
                continue;
            }
            Component c = component.findComponentById(onClick.componentId());
            if (c == null) {
                continue;
            }
            c.setClickedListener((view) -> {
                method.setAccessible(true);
                try {
                    int count = method.getParameterCount();
                    if (count == 0) {
                        method.invoke(this);
                    } else if (count == 1) {
                        method.invoke(this, view);
                    } else {
                        throw new IllegalArgumentException("参数数量只能为0或者1个");
                    }
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            });
        }
    }

    /**
     * 重写此方法，定制悬浮窗组件长按事件
     *
     * @param component 悬浮出啊主布局对象，通过此对象可以找到悬浮穿中，所有组件需要注入长按事件的Component对象
     */
    protected void initLongClick(Component component) {
        Class<? extends SimplePopup> aClass = this.getClass();
        Method[] methods = aClass.getDeclaredMethods();
        for (Method method : methods) {
            OnLongClick longClick = method.getDeclaredAnnotation(OnLongClick.class);
            if (longClick == null) {
                continue;
            }
            Component c = component.findComponentById(longClick.componentId());
            if (c == null) {
                continue;
            }
            c.setLongClickedListener(view -> {
                method.setAccessible(true);
                try {
                    int count = method.getParameterCount();
                    if (count == 0) {
                        method.invoke(this);
                    } else if (count == 1) {
                        method.invoke(this, view);
                    } else {
                        throw new IllegalArgumentException("参数数量只能为0或者1个");
                    }
                } catch (IllegalAccessException | InvocationTargetException e) {
                    e.printStackTrace();
                }
            });
        }
    }
}
